import {Point} from "../../../../nodeApp/static/lib/crowncad-plugin-sdk-0.0.1";
import {symmetryPoint} from "../../../util/Common";

export class GearParams{
  constructor(z = 17, m = 2, alpha = 20, faceWidth = 10, helixDirection = 'leftHelix',
              helixAngle = 15) {
    /**
     * 齿数 z （5≤z≤200）
     */
    this.teethNumber = z;

    /**
     * 模数 m
     */
    this.module = m;

    /**
     * 压力角 α（10deg≤α≤20deg），此处转换为弧度值
     */
    this.alpha = alpha / 180 * Math.PI;

    /**
     * 齿距 p = m * π
     * 齿厚：齿轮齿面厚度
     */
    this.teethPitch = m * Math.PI;

    /**
     * 齿宽，即柱齿轮拉伸长度
     */
    this.teethWidth = faceWidth;

    /**
     * 齿根圆角半径 rr = 0.38 * m
     */
    this.teethFilterR = 0.38 * m;

    /**
     * 齿顶高系数 ha*
     * ha* = ha / m
     * 正常齿：1
     * 短齿：0.8
     * ha: 齿顶高，分度圆到齿顶圆之间的径向距离
     */
    this.addendumCoefficient = 1;
    this.ha = this.addendumCoefficient * m;

    /**
     * 齿根高系数 hf*
     * hf* = hf / m
     * hf* = 1.25,当 m>1.25时
     * hf* =1.4,当 m≤1.25 时
     * hf 齿根高，分度圆到齿根圆之间的径向距离
     */
    if (m > 1.25) {
      this.dedendumCoefficient = 1.25;
    } else {
      this.dedendumCoefficient = 1.4;
    }
    this.hf = this.dedendumCoefficient * m;

    /**
     * 分度圆半径 rp = m * z / 2
     * 分度圆直径 dp
     */
    this.rp = this.module * this.teethNumber / 2;
    this.dividingD = this.rp * 2;

    /**
     * 基元半径 rb = rp * cos(α)， 此处α为弧度值
     * 基圆直径 db
     */
    this.rb = this.rp * Math.cos(this.alpha);
    this.baseD = this.rb * 2;

    /**
     * 齿顶圆半径 ra = rp + ha
     * 齿顶圆直径 da
     */
    this.ra = this.rp + this.ha;
    this.addendumD = this.ra * 2;

    /**
     * 齿根圆半径 rf = rp - hf
     * 齿根圆直径 df
     */
    this.rf = this.rp - this.hf;
    this.dedendumD = this.rf * 2;

    /**
     * 柱斜齿轮螺旋方向，左旋：1；右旋：2
     */
    if (helixDirection === 'leftHelix') {
      this.helixDirection = 1;
    } else if (helixDirection === 'rightHelix') {
      this.helixDirection = 2;
    }

    /**
     * 柱斜齿轮的分度圆螺旋角 b，此处转换为弧度值
     */
    this.helixAngle = helixAngle  / 180 * Math.PI;
  }

  //初始化圆锥齿轮数据
  initBevelGearData(coneAngle = 45, addendumCoefficient = 1.0,  clearanceCoefficient = 0.2,
              helixDirection = '', helixAngle = 0,
                    addendumModiCoef = 0.0, tangentialModiCoef = 0.0) {
    /**
     * 节锥角
     * @type {number}
     */
    this.deltaA = coneAngle;
    this.delta = this.deltaA / 180 * Math.PI;

    /**
     * 齿距 p = m * π
     * 齿厚：齿轮齿面厚度
     */
    this.teethPitch = this.module * Math.PI;

    /**
     * 齿根圆角半径 rr = 0.38 * m
     */
    this.teethFilterR = 0.2 * this.module;

    /**
     * 齿顶高系数 ha*
     * ha* = ha / m
     * 正常齿：1
     * 短齿：0.8
     * ha: 齿顶高，分度圆到齿顶圆之间的径向距离
     */
    this.hax = addendumCoefficient; //齿顶高系数
    this.ha = this.hax * this.module;

    /**
     * 齿根高系数 hf*
     * hf* = hf / m
     * hf* = 1.25,当 m>1.25时
     * hf* =1.4,当 m≤1.25 时
     * hf 齿根高，分度圆到齿根圆之间的径向距离
     */
    this.cx = clearanceCoefficient;
    this.hf = (this.hax + this.cx) * this.module;

    /**
     * 分度圆半径 rp = m * z / 2
     * 分度圆直径 dp
     */
    this.dp = this.module * this.teethNumber;
    this.rp = this.dp / 2;

    /**
     * 基元半径 rb = rp * cos(α)， 此处α为弧度值
     * 基圆直径 db
     */
    this.db = this.dp * Math.cos(this.alpha);
    this.rb = this.db / 2;

    /**
     * 齿顶圆半径 ra = rp + ha
     * 齿顶圆直径 da
     */
    this.da = this.dp + 2 * this.ha * Math.cos(this.delta);
    this.ra = this.da / 2;

    /**
     * 齿根圆半径 rf = rp - hf
     * 齿根圆直径 df
     */
    this.df = this.dp - 2 * this.hf * Math.cos(this.delta);
    this.rf = this.df / 2;

    /**
     * 柱斜齿轮螺旋方向，左旋：1；右旋：2；直齿轮:0
     */
    this.helixDirection = 0;
    if (helixDirection === 'leftHelix') {
      this.helixDirection = 1;
      this.helixAngle = helixAngle;
    } else if (helixDirection === 'rightHelix') {
      this.helixDirection = 2;
      this.helixAngle = -helixAngle;
    }

    /**
     *参考Proe创建齿轮的计算公式
     */
    this.hb = (this.dp - this.db) / (2 * Math.cos(this.delta));
    this.rx = this.dp / (2 * Math.sin(this.delta));
    this.theta_a = Math.atan(this.ha / this.rx);
    this.theta_b = Math.atan(this.hb / this.rx);
    this.theta_f = Math.atan(this.hf / this.rx);
    this.delta_a = this.delta + this.theta_a;
    this.delta_b = this.delta - this.theta_b;
    this.delta_f = this.delta - this.theta_f;
    this.ba = this.teethWidth / Math.cos(this.theta_a);
    this.bb = this.teethWidth / Math.cos(this.theta_b);
    this.bf = this.teethWidth / Math.cos(this.theta_f);
    //齿轮大端关系式
    this.dp1 = this.dp / Math.cos(this.delta);
    this.rp1 = this.dp1 / 2;
    this.da1 = this.da / Math.cos(this.delta);
    this.ra1 = this.da1 / 2;
    this.db1 = this.db / Math.cos(this.delta);
    this.rb1 = this.db1 / 2;
    this.df1 = this.df / Math.cos(this.delta);
    this.rf1 = this.df1 / 2;
    //齿轮小端关系式
    this.dp2 = (this.dp - 2 * this.teethWidth * Math.sin(this.delta)) / Math.cos(this.delta);
    this.rp2 = this.dp2 / 2;
    this.da2 = (this.da - 2 * this.ba * Math.sin(this.delta_a)) / Math.cos(this.delta);
    this.ra2 = this.da2 / 2;
    this.db2 = (this.db - 2 * this.bb * Math.sin(this.delta_b)) / Math.cos(this.delta);
    this.rb2 = this.db2 / 2;
    this.df2 = (this.df - 2 * this.bf * Math.sin(this.delta_f)) / Math.cos(this.delta);
    this.rf2 = this.df2 / 2;
    /**
     * 全齿高
     */
    this.h = (2 * this.hax + this.cx) * this.module;
    //上下两个圆锥体的半径
    this.r1 = (this.rf1 - this.h) * Math.cos(this.delta);
    this.r2 = this.rf1 * Math.cos(this.delta);
    this.r3 = (this.rf2 - this.h * 0.8) * Math.cos(this.delta);
    //上下两个圆锥体的高度
    this.height1 = this.h * Math.sin(this.delta);
    this.height2 = this.h * 0.8 * Math.sin(this.delta);
    //圆心在x轴上的位置
    this.circleCenter1 = this.rf1 * Math.sin(this.delta);
    //中间凸台的草图点
    this.x1 = this.rf1 * Math.sin(this.delta);
    this.y1 = 0;
    this.x2 = this.x1;
    this.y2 = this.rf1 * Math.cos(this.delta);
    this.x3 = this.ra1 * Math.sin(this.delta);
    this.y3 = this.ra1 * Math.cos(this.delta);
    let offset = this.teethWidth / Math.cos(this.delta);
    this.x4 = this.ra2 * Math.sin(this.delta) + offset - 0.6;
    this.y4 = this.ra2 * Math.cos(this.delta) - 0.4;
    this.x5 = this.rf2 * Math.sin(this.delta) + offset - 0.1;
    this.y5 = this.rf2 * Math.cos(this.delta);
    this.x6 = this.x5;
    this.y6 = 0;
  }
  //圆柱齿轮参数判断
  analysisGearParams() {
    //半径比较
    let status = true;
    if(this.rf < this.rb && this.rb < this.rp && this.rp < this.ra) {
      status = true;
    } else if(this.rb < this.rf) {
      const angle = Math.PI / 2;

      const QPoint = this.getIntersectionPointInInvolute(0, angle, this.rb, this.rp);
      const theta = Math.PI / (2 * this.teethNumber);
      const mX = QPoint.x * Math.cos(theta) - QPoint.y * Math.sin(theta);
      const mY = QPoint.x * Math.sin(theta) + QPoint.y * Math.cos(theta);
      const MPoint = new THREE.Vector3(mX, mY);
      const OPoint = new THREE.Vector3(0, 0);

      const interPoint = this.getIntersectionPointInInvolute(0, angle, this.rb, this.rf);
      let rightP = this.getPoint(interPoint);
      let leftP = this.getPoint(symmetryPoint(new THREE.Vector3(interPoint.x, interPoint.y), OPoint, MPoint));
      if(rightP.x < leftP.x) {
        status = false;
      }
    } else {
      status = false;
    }
    return status;
  }
  // 获取基圆在 [startAngle, endAngle] 之间渐开线与目标圆的交点
  getIntersectionPointInInvolute(startAngle, endAngle, baseR, targetR) {
    const midAngle = (startAngle + endAngle) / 2;
    const x = baseR * (Math.sin(midAngle) - midAngle * Math.cos(midAngle));
    const y = baseR * (Math.cos(midAngle) + midAngle * Math.sin(midAngle));
    const delta = Math.sqrt(x * x + y * y) - targetR;
    if (Math.abs(delta) < 0.001) {
      return {x, y};
    }
    let diff = endAngle - startAngle;
    if (delta > 0 && diff > 0.000001) {  // 二分中点在目标圆外部
      return this.getIntersectionPointInInvolute(startAngle, midAngle, baseR, targetR);
    } else if (delta < 0 && diff > 0.000001) {  // 二分中点在目标圆内部
      return this.getIntersectionPointInInvolute(midAngle, endAngle, baseR, targetR);
    } else if (delta < 0 && diff < 0.000001) {  // 二分中点在目标圆内部
      return this.getIntersectionPointInInvolute(midAngle, endAngle + 0.1, baseR, targetR);
    }
  }
  // 处理点坐标的误差
  getPoint(point) {
    const x = Math.abs(point.x) < 1e-10 ? 0 : point.x;
    const y = Math.abs(point.y) < 1e-10 ? 0 : point.y;
    return new Point(x, y);
  }
}
